#include "datablock.h"

datablock::datablock()
{

}

vector<int> datablock::getDataBlocks(int versionINFO, int maskPattern, point origin, int pixelProportion, QImage *img)
{
    vector<int> blocks;
    int word = 0;
    int blockCounter = 7;
    int lastCol = origin.getColumn();
    int lastRowUp = origin.getRow();
    int lastRowDown = origin.getRow()+(16+4*versionINFO)*pixelProportion;
    int row = lastRowDown;
    int col = origin.getColumn()+(16+4*versionINFO)*pixelProportion;

    pixel p;

    while (col > lastCol)
    {
        if (row != lastRowUp)
        {
            while (row >= lastRowUp)
            {
                for (int i = 0; i <= pixelProportion; i += pixelProportion)
                {
                    if (!p.isPattern(row, col-i, img))
                    {
                        unMask(row, col-i, maskPattern, origin, pixelProportion, img);
                        if (p.isPixelBlack(row, col-i, img))
                            word += 1 << blockCounter;
                        blockCounter--;
                        if (blockCounter == -1)
                        {
                            blocks.push_back(word);
                            word = 0;
                            blockCounter = 7;
                        }
                    }
                }
                row -= pixelProportion;
            }
            row += pixelProportion;
        }
        else
        {
            while (row <= lastRowDown)
            {
                for (int i = 0; i <= pixelProportion; i += pixelProportion)
                {
                    if (!p.isPattern(row, col-i, img))
                    {
                        unMask(row, col-i, maskPattern, origin, pixelProportion, img);
                        if (p.isPixelBlack(row, col-i, img))
                            word += 1 << blockCounter;
                        blockCounter--;
                        if (blockCounter == -1)
                        {
                            blocks.push_back(word);
                            word = 0;
                            blockCounter = 7;
                        }
                    }
                }
                row += pixelProportion;
            }
            row -= pixelProportion;
        }
        col -= 2*pixelProportion;
    }

    return blocks;
}

void datablock::unMask(int row, int col, int maskPattern, point origin, int pixelProportion, QImage *img)
{
    int x = (row-origin.getRow())/pixelProportion;
    int y = (col-origin.getColumn())/pixelProportion;
    bool notReverse;

    pixel p;

    switch (maskPattern) {
        case 0: // 000
            if ((x + y) % 2 == 0)
                p.reversePixel(row, col, pixelProportion, img);
            else
                notReverse = true;
            break;
        case 1: // 001
            if (x % 2 == 0)
                p.reversePixel(row, col, pixelProportion, img);
            else
                notReverse = true;
            break;
        case 2: // 010
            if (y % 3 == 0)
                p.reversePixel(row, col, pixelProportion, img);
            else
                notReverse = true;
            break;
        case 3: // 011
            if ((x + y) % 3 == 0)
                p.reversePixel(row, col, pixelProportion, img);
            else
                notReverse = true;
            break;
        case 4: // 100
            if ((x / 2 + y / 3) % 2 == 0)
                p.reversePixel(row, col, pixelProportion, img);
            else
                notReverse = true;
            break;
        case 5: // 101
            if ((x * y) % 2 + (x * y) % 3 == 0)
                p.reversePixel(row, col, pixelProportion, img);
            else
                notReverse = true;
            break;
        case 6: // 110
            if (((x * y) % 2 + (x * y) % 3) % 2 == 0)
                p.reversePixel(row, col, pixelProportion, img);
            else
                notReverse = true;
            break;
        case 7: // 111
            if (((x * y) % 3 + (x + y) % 2) % 2 == 0)
                p.reversePixel(row, col, pixelProportion, img);
            else
                notReverse = true;
            break;
        }
    if (notReverse)
    {
        if (p.isPixelBlack(row, col, img))
            p.paintPixel(row, col, pixelProportion, qRgb(0,0,0), img);
        else
            p.paintPixel(row, col, pixelProportion, qRgb(255,255,255), img);
    }
}

string datablock::decodeDataBlocks(vector<int> dataBlocks, int versionINFO)
{
    converter c;
    int mode;
    int sizeDataLenght;
    int numBlock = 0;
    string data = "";

    mode = (dataBlocks[numBlock] & 240) >> 4;
    log->addLog("\nMODE = " + c.intToString(mode));
    sizeDataLenght = 0;
    if (versionINFO <= 9)
    {
        sizeDataLenght = (dataBlocks[numBlock] & 15) << 4;
        sizeDataLenght += (dataBlocks[numBlock+1]) >> 4;
        numBlock++;
    }
    else
    {
        sizeDataLenght = (dataBlocks[numBlock] & 15) << 12;
        sizeDataLenght += (dataBlocks[numBlock+1]) << 4;
        sizeDataLenght += (dataBlocks[numBlock+2] & 240) >> 4;
        numBlock += 2;
    }
    log->addLog("\nNUMERO DE CARACTERES = " + c.intToString(sizeDataLenght));

    switch (mode) {
        case NUMERIC_MODE:
            data = decodeNumeric(sizeDataLenght, &numBlock, dataBlocks);
            break;
        case ALPHA_NUMERIC_MODE:
            data = decodeAlnum(sizeDataLenght, &numBlock, dataBlocks);
            break;
        case BINARY_MODE:
            data = decodeBinary(sizeDataLenght, &numBlock, dataBlocks);
            break;
        case JAPANESE_MODE:
            data = decodeJapanese(sizeDataLenght, &numBlock, dataBlocks);
            break;
    }

    return data;
}
/*== Numeric Decoder not implemented  ==*/
string datablock::decodeNumeric(int sizeDataLenght, int *numBlock, vector<int> dataBlocks)
{
    string data = "";
    return data;
}
/*== Alnum Decoder not implemented ==*/
string datablock::decodeAlnum(int sizeDataLenght, int *numBlock, vector<int> dataBlocks)
{
    string data = "";
    return data;
}

string datablock::decodeBinary(int sizeDataLenght, int *numBlock, vector<int> dataBlocks)
{
    int intData;
    string data = "";
    for (int i = 0; i < sizeDataLenght; i++)
    {
        intData = (dataBlocks[*numBlock] & 15) << 4;
        intData += (dataBlocks[++(*numBlock)]) >> 4;
        data += (char) intData;
    }

    return data;
}
/*== Kanji Decoder not implemented ==*/
string datablock::decodeJapanese(int sizeDataLenght, int *numBlock, vector<int> dataBlocks)
{
    string data = "";
    return data;
}

void datablock::setCanvas(canvas *log)
{
    this->log = log;
}
